package in.waffl.fairycake;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;
import java.util.PriorityQueue;

public class Canvas extends java.awt.Canvas {
	private static final long serialVersionUID = 2594898656404467380L;
	DrawableComparator comp = new DrawableComparator();
	private final PriorityQueue<Drawable> drawQueue;
	private boolean drawing = false;
	private Thread drawThread;
	private boolean paused = false;
	
	public Canvas() {
		drawQueue = new PriorityQueue<Drawable>(10, new DrawableComparator());
		setBackground(Color.BLACK);
		setPreferredSize(new Dimension(640, 480));
		final Canvas canvas = this;
		drawThread = new Thread(new Runnable() {
			@Override
			public void run() {
				for (;;) {
					try {
						BufferStrategy buffer = canvas.getBufferStrategy();
						for (;;) {
							long start = System.currentTimeMillis();
							canvas.paint(buffer);
							long lag = System.currentTimeMillis()-start;
							try {
								if ((1000/Main.FPS) - lag > 0) Thread.sleep((1000/Main.FPS) - lag);
								while(isPaused()) {
									Thread.sleep(10);
								}
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				} 
			}
		});
	}
	public void paint(Graphics g) {
	}
	public void paint(BufferStrategy b) {
		synchronized(drawQueue) {
			Graphics2D g = (Graphics2D) b.getDrawGraphics();
			if (drawing) return;
			drawing = true;
			//g.setColor(Color.black);
			//g.fillRect(0, 0, 640, 480);
			PriorityQueue<Drawable> tempQueue = new PriorityQueue<Drawable>(10, comp);
			while (!drawQueue.isEmpty()) {
				Drawable d = drawQueue.poll();
				if (d != null) {
					d.draw(g);
					if (!d.destroy) tempQueue.add(d);
				}
			}
			drawQueue.addAll(tempQueue);
			if(!b.contentsLost()) b.show();
			drawing = false;
		}
	}
	public void addDrawable(Drawable d) {
		synchronized(drawQueue) {
			drawQueue.offer(d);
		}
	}
	public void destroyAllDrawables() {
		synchronized(drawQueue) {
			drawQueue.clear();
		}
	}
	public void pause() {
		paused = true;
	}
	public void unpause() {
		paused = false;
	}
	public boolean isPaused() {
		return paused;
	}
	public void start() {
		drawThread.start();
	}
}
